<?php


namespace loan;


use app\common\lib\RedisKey;
use custom\Err;
use custom\Redis;

class Mortgage {

    /**
     * 相差金额大于该金额进行拆分
     */
    const DIFF_MONEY = 10;

    /**
     * 拆分份数n,该值 = n -1
     */
    const SPLIT_NUM = 4;

    /**
     * 缓存时间 1小时
     */
    const EXPIRE = 3600;

    /**
     * 获取列表
     * @param $id 列表所在计算id
     * @return array
     */
    public static function getList($id) {

        $redisKey = RedisKey::LOAN_BUSINESS_HOUSE . "_" . $id;
        if (!$data = Redis::getInstance()->get($redisKey)) {
            return [];
        }

        $data = json_decode($data, true);

        $list = [];
        foreach ($data as $key => &$val) {
            $val = get_array_by_keys($val, 'total,need_money,monthly');
            $list[] = array_merge($val, ['id' => "{$id}_{$key}"]);
        }

        return $list;
    }

    /**
     * 获取详情
     * @param $id
     * @return array
     */
    public static function getInfo($id) {
        list($id, $childrenId) = explode('_', $id);

        $redisKey = RedisKey::LOAN_BUSINESS_HOUSE . "_" . $id;
        if (!$data = Redis::getInstance()->get($redisKey)) {
            return [];
        }
        $data = json_decode($data, true);

        foreach ($data as $key => &$val) {
            if ($key == $childrenId) {
                return $val;
            }
        }

        return [];
    }

    /**
     * 房贷计算
     * @param $params
     * @return string
     */
    public static function mortgageCount($params) {

        if (!static::checkParams($params)) {
            return false;
        }

        $id = uniqid12();
        $list = [];
        static::handleData($params);

        foreach ($params['money'] as $key => $money) {

            // 首付款
            $firstMoney = round($money * $params['ratio'] / 10, 2);
            // 贷款总额
            $loanMoney = round($money - $firstMoney, 2);
            // 贷款总额：万->元
            $loanMoneyElement = $loanMoney * 10000;
            // 等额本息贷款
            $interest = RateCount::interest($loanMoneyElement, $params['rate'], $params['stage']);
            // 等额本金贷款
            $capital = RateCount::capital($loanMoneyElement, $params['rate'], $params['stage']);

            // 是否税费测算
            $taxation = [];
            if ($params['is_taxation'] == 1) {
                $taxation = static::taxationCount($money * 10000, $loanMoneyElement, $params);
            }

            $list[ $key ] = static::assemblyData($money, $firstMoney, $params, $taxation, $interest, $capital);
        }

        // 存入缓存
        $redisKey = RedisKey::LOAN_BUSINESS_HOUSE . "_" . $id;
        Redis::getInstance()->set($redisKey, json_encode($list), ['EX' => self::EXPIRE]);
        return $id;
    }

    /**
     * 数据组装
     * @param $money 预估成交价
     * @param $firstMoney 首付款
     * @param $params 参数
     * @param $taxation 税费测算
     * @param $interest 等额本息
     * @param $capital 等额本金
     * @return array
     */
    private static function assemblyData($money, $firstMoney, $params, $taxation, $interest, $capital) {

        // 需要准备的费用
        $yuan = $n = $p = $g = $d = $pe = 0;
        if($params['is_taxation'] == 1) {
            $n = $params['notarial_fees'] ?? 0;
            $p = $params['property_fee'] ?? 0;
            $g = $taxation['guarantee_fee'] ?? 0;
            $d = $taxation['deed_tax'] ?? 0;
            $pe = $taxation['person_tax'] ?? 0;
            $yuan = $n + $p + $g + $d + $pe;
        }

        $needMoney = $yuan == 0 ? $firstMoney : $firstMoney + round($yuan / 10000, 2);

        return [
            'total'         => (string)$money, // 屋价总款
            'stage'         => (string)$params['stage'], // 期数，转换成年需要除以12
            'need_money'    => (string)$needMoney, // 需要准备费用
            'monthly'       => money_mil($interest['firstMoney']), // 月供
            'ratio'         => (string)$params['ratio'], // 首付比例
            'guarantee_fee' => money_mil($g), // 担保费
            'deed_tax'      => money_mil($d), // 契税
            'person_tax'    => money_mil($pe), // 个税
            'notarial_fees' => money_mil($n), // 公证费
            'property_fee'  => money_mil($p), // 物业费
            // 等额本息
            'interest'      => [
                'monthly'        => money_mil($interest['firstMoney']), // 月供
                'first_money'    => (string)$firstMoney, // 首付
                'interest_total' => (string)$interest['interestTotal'], // 总利息
                'total'          => (string)$interest['total'], // 总贷款额
                'info'           => $interest['info'], // 贷款详情
            ],
            // 等额本金
            'capital'       => [
                'monthly'        => money_mil($capital['firstMoney']), // 月供
                'first_money'    => (string)$firstMoney, // 首付
                'interest_total' => (string)$capital['interestTotal'], // 总利息
                'total'          => (string)$capital['total'], // 总贷款额
                'diff'           => $capital['diff'],
                'info'           => $capital['info'], // 贷款详情
            ],
        ];

    }

    /**
     * 税费测算
     * @param $money 房屋总额：元
     * @param $loanMoneyElement 贷款总额：元
     * @param $params 参数
     * @return array
     */
    private static function taxationCount($money, $loanMoneyElement, $params) {

        $data = [];
        // 担保费
        $data['guarantee_fee'] = round($loanMoneyElement * $params['guarantee']);
        // 契税
        $data['deed_tax'] = round($money * $params['deed_tax']);
        // 个税
        $data['person_tax'] = round($money * $params['person_tax']);

        return $data;
    }

    /**
     * 数据处理
     * @param $params
     */
    private static function handleData(&$params) {

        /*金额处理*/
        $money = [];
        if($params['min'] <= $params['max']) {
            $params['min'] > 0 && $money[] = $params['min'];
            $params['max'] > 0 && $money[] = $params['max'];
        }else{
            $params['max'] > 0 && $money[] = $params['max'];
            $params['min'] > 0 && $money[] = $params['min'];
        }

        // 默认取该区间值
        $params['money'] = $money;
        // 存在最大和最小值
        if (isset($money[1])) {
            // 求差积
            $diff = $money[1] - $money[0];
            // 相差大于设置金额，拆分
            if ($diff >= self::DIFF_MONEY) {
                $params['money'] = static::splitMoney($money[0], $money[1], $diff);
            }

        }

        /*利率处理*/
        $params['rate'] = $params['rate'] / 100;
        $params['guarantee'] = $params['guarantee'] / 100;
        $params['deed_tax'] = $params['deed_tax'] / 100;
        $params['person_tax'] = $params['person_tax'] / 100;
    }

    /**
     * 拆分金额
     * @param $min
     * @param $max
     * @param $diff
     * @return array
     */
    private static function splitMoney($min, $max, $diff) {
        // 平均差积
        $averageDiff = round($diff / self::SPLIT_NUM, 2);
        $money[] = $min;
        for ($i = 0; $i < self::SPLIT_NUM - 1; ++$i) {
            $money[] = $money[ $i ] + $averageDiff;
        }
        $money[] = $max;
        return $money;
    }

    /**
     * 参数验证
     * @param $params
     * @return bool
     */
    private static function checkParams($params) {
        // 预估成交价
        if ($params['min'] + $params['max'] <= 0) {
            Err::add('预估成交价不能都为0');
            return false;
        }
        // 首付比例
        if ($params['ratio'] >= 10 || $params['ratio'] == 0) {
            Err::add('首付比例错误');
            return false;
        }

        // 按揭期数
        if ($params['stage'] % 12 > 0) {
            Err::add('按揭期数错误');
            return false;
        }

        return true;
    }

}